package com.jnc.web.biz.tool.service.impl;

import com.jnc.common.constant.SysConstant;
import com.jnc.core.properties.GlobalProperties;
import com.jnc.web.biz.tool.mapper.GenMapper;
import com.jnc.web.biz.tool.model.ColumnInfo;
import com.jnc.web.biz.tool.model.TableInfo;
import com.jnc.web.biz.tool.service.GenService;
import com.jnc.web.util.gen.GenUtil;
import com.jnc.web.util.gen.VelocityFactory;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @Author: jjn
 * @Date: 2018/11/14
 * @Desc:
 */
@Slf4j
@Service
public class GenServiceImpl implements GenService {
    @Autowired
    GenUtil genUtil;
    @Autowired
    GlobalProperties globalProperties;
    @Autowired
    private GenMapper genMapper;

    /**
     * 查询指定数据库所有表信息
     * @param tableInfo  表信息
     * @return
     */
    @Override
    public List<TableInfo> queryTableList(TableInfo tableInfo) {
        return genMapper.queryTableList(tableInfo);
    }

    /**
     * 生成代码
     * @param tableName 表名称
     * @return
     */
    @Override
    public byte[] generatorCode(String tableName) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);
        //查询表信息
        TableInfo tableInfo = genMapper.queryTableByName(tableName);
        //查询列信息
        List<ColumnInfo> columns = genMapper.queryTableColumnsByName(tableName);
        //生成代码
        generatorCode(tableInfo, columns, zip);
        IOUtils.closeQuietly(zip);
        return outputStream.toByteArray();
    }

    /**
     * 批量生成代码
     * @param tableNames 表数组
     * @return
     */
    @Override
    public byte[] generatorCode(String[] tableNames) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);
        for (String tableName : tableNames){
            // 查询表信息
            TableInfo table = genMapper.queryTableByName(tableName);
            // 查询列信息
            List<ColumnInfo> columns = genMapper.queryTableColumnsByName(tableName);
            // 生成代码
            generatorCode(table, columns, zip);
        }
        IOUtils.closeQuietly(zip);
        return outputStream.toByteArray();
    }


    private void generatorCode(TableInfo tableInfo, List<ColumnInfo> columns, ZipOutputStream zip){
        //表名转换成Java属性名
        String className = genUtil.tableToJava(tableInfo.getTableName());
        tableInfo.setClassName(className);
        tableInfo.setClassname(StringUtils.uncapitalize(className));
        //列信息
        tableInfo.setColumns(genUtil.transColumns(columns));
        //设置主键
        tableInfo.setPrimaryKey(tableInfo.getColumnsLast());
        //初始化Velocity引擎
        VelocityFactory.init();

        String packageName = globalProperties.getPackageName();
        String moduleName = genUtil.getModuleName(packageName);
        //获取初始化模板参数
        VelocityContext context = genUtil.getVelocityContext(tableInfo);

        //获取模板列表
        List<String> templates = genUtil.getTemplates();
        for (String template : templates){
            //渲染模板
            StringWriter sw = new StringWriter();
            Template tpl = Velocity.getTemplate(template, SysConstant.CHARSET_NAME);
            tpl.merge(context, sw);

            //添加到zip
            try {
                zip.putNextEntry(new ZipEntry(genUtil.getFileName(template, tableInfo, moduleName)));
                IOUtils.write(sw.toString(), zip, SysConstant.CHARSET_NAME);
                IOUtils.closeQuietly(sw);
                zip.closeEntry();
            } catch (IOException e) {
                log.error("Generator code error, table name is {}, Exception: {}", tableInfo.getTableName(), ExceptionUtils.getStackTrace(e));
            }
        }
    }
}
